using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Collections;


namespace TEAM.SerialTXRX
{
    public class SerialHelper: Form
    {
        SerialPortSettings serialPortSettings1 = new SerialPortSettings("COM15", 19200);
        private SerialDevice serial;
        private delegate void LogDelegate(string text);
        private delegate void ShowDataDelegate(byte[] data);
        private string hexPrefix = String.Empty; //gets changed to "0x" if user enables the prefix option
        private string delimiter = " "; //default is space, can be changed by user
        private StringBuilder immediateASCIIhistory = new StringBuilder(100); // twice as big as it needs to be, to allow some leeway?
        private Control Show = new Control();
        private Control LogControl = new Control();

        public SerialInfo SerialIntoTxRx = new SerialInfo();

        string _info = String.Empty;
        string _error = String.Empty;
        string _command = String.Empty;
        private TextBox txtReceivedData;
        string _data;

        public string Info
        {
            get { return _info; }
            set { _info = value; }
        }
        public string Error
        {
            get { return _error; }
            set { _error = value; }
        }
        public string Command
        {
            get { return _command; }
            set { _command = value; }
        }

        public string ReceivedData
        {
            get { return _data; }
            set { _data = value; }
        }

        public SerialHelper()
            : base()
        {
            int[] baudRates = { 19200 };
            serial = new SerialDevice(baudRates, 19200);
            serialPortSettings1.Initialize(serial);
            serial.ReportInfo += new SerialDevice.InformationEventHandler(LogInfoD);
            serial.ReportError += new SerialDevice.ErrorEventHandler(LogErrorD);
            serial.ReportCommand += new SerialDevice.CommandEventHandler(LogCommandD);
            serial.ReceiveData += new SerialDevice.ReceiveDataEventHandler(ShowDataD);
        }

        private void LogInfoD(string text)
        {
            //LogControl.Invoke(new LogDelegate(LogInfo), new object[] { text });
            //txtInfo.Invoke(new LogDelegate(LogInfo), new object[] { text });
            LogInfo(text);
        }
        private void LogErrorD(string text)
        {
            //LogControl.Invoke(new LogDelegate(LogError), new object[] { text });
            //txtError.Invoke(new LogDelegate(LogError), new object[] { text });
            LogError(text);
        }
        private void LogCommandD(string text)
        {
            //LogControl.Invoke(new LogDelegate(LogCommand), new object[] { text });
            //txtError.Invoke(new LogDelegate(LogCommand), new object[] { text });
            LogCommand(text);
        }

        private void ShowDataD(byte[] data)
        {
            //Show.Invoke(new ShowDataDelegate(ShowData), new object[] { data });
            //txtReceivedData.Invoke(new ShowDataDelegate(ShowData), new object[] { data });
            //ShowData(data);
        }

        private void LogInfo(string text)
        {
            SerialIntoTxRx.Info = text;
            //txtReceivedData.Text = text;
        }
        private void LogError(string text)
        {
            SerialIntoTxRx.Error = text;
            //txtReceivedData.Text = text;
        }
        private void LogCommand(string text)
        {
            SerialIntoTxRx.Command = text;
            //txtReceivedData.Text = text;
        }

        public string getDataReceived()
        {
            return ShowData(serial.DataReceivedFromSerialPort());
        }

        private string ShowData(byte[] data)
        {
            data = serial.DataReceivedFromSerialPort();
            string HexData = String.Empty;
            foreach (byte b in data)
            {
                HexData = HexData + String.Format("{0}{1:X2}{2}", hexPrefix, b, delimiter);
            }
            SerialIntoTxRx.ReceivedData = HexData;
            return HexData;
        }

        public void SendHex(string TransmitHex)
        {
            // strip the input of all delimiter characters and the optional 0x prefix
            string data = TransmitHex.Replace("0x", String.Empty).Replace(@"\n", "0A").Replace(@"\r", "0D").Replace(delimiter, String.Empty).Replace(",", String.Empty).Replace(" ", String.Empty).ToUpper();

            // check for invalid characters
            string invalidChars = String.Empty;
            for (int i = 0; i < data.Length; i++)
            {
                if (!Char.IsDigit(data[i]) && !(data[i] >= 'A' && data[i] <= 'F'))
                {
                    if (!invalidChars.Contains(data.Substring(i, 1)))
                    {
                        invalidChars += data[i];
                    }
                }
            }
            // report any invalid characters
            if (invalidChars != String.Empty)
            {
                LogError("Invalid characters detected (non-Hex, non-delimiter characters): " + invalidChars);
                return;
            }
            // require an even number of hex characters
            if (data.Length % 2 != 0)
            {
                LogError("Must have an even number of hex characters. You supplied " + data.Length + " characters.");
                return;
            }

            // convert the hex characters to a byte array
            byte[] buffer = new byte[data.Length / 2];
            for (int i = 0; i < data.Length; i += 2)
            {
                buffer[i / 2] = byte.Parse(data.Substring(i, 2), System.Globalization.NumberStyles.AllowHexSpecifier);
            }

            // Convert to displayable hex format, with 0x prefix if enabled, and the configured delimiter
            StringBuilder command = new StringBuilder(buffer.Length * (hexPrefix.Length + 2 + delimiter.Length));
            foreach (byte b in buffer)
            {
                if (b == '\r')
                {
                    command.Append(@"\r");
                    command.Append(delimiter);
                }
                else if (b == '\n')
                {
                    command.Append(@"\n");
                    command.Append(delimiter);
                }
                else
                {
                    command.Append(String.Format("{0}{1:X2}{2}", hexPrefix, b, delimiter));
                }
            }

            // Log the command and write it out to the serial port
            LogCommand(command.ToString());
            serial.serialWrite(buffer);
        }

    }
}
